package com.wsepr.flexreport.core
{
    import flash.utils.describeType;
    
    import mx.core.Container;
    import mx.core.UIComponent;
    import mx.utils.StringUtil;
    
    import r1.deval.D;
    
    import spark.components.Group;
    import spark.components.SkinnableContainer;

    public class PageBuilder
    {
        private const NAME_SPACE_MAPPING:Object={
            'library://ns.adobe.com/flex/mx':['mx.containers.','mx.controls.','mx.controls.dataGridClasses.'],
            'library://ns.adobe.com/flex/spark':['spark.components.']
        };
        
        public function PageBuilder()
        {
        }
        
        /**
        * 解析mxml字符串，创建组件
        * */
        public function parseMXML(mxml:String):FlexPage{
            if(mxml == null || StringUtil.trim(mxml) == ''){
                return null;
            }
            var mxmlXML:XML = new XML(mxml);
            var page:FlexPage = new FlexPage();
            trace(mxmlXML.localName());
            var component:Object = createComponent(mxmlXML.localName(), mxmlXML.namespace());
            setProperty(mxmlXML, component);
            page.putComponentToContext(component);
            visitNode(mxmlXML.children(), page, component);
            page.ui = component as UIComponent;
            return page;
        }
        
        //遍历所有节点
        private function visitNode(children:XMLList, page:FlexPage, parent:Object):void{
            var nextParent:Object = null;
            for each(var xml:XML in children){
                trace('节点类型：'+xml.nodeKind()+' 值：'+xml.toString());
                if(xml.nodeKind() == 'element'){
                    trace("=="+xml.name());
                    if(isContainer(parent) || !(parent is UIComponent)){
                        var component:Object = componentHandler(xml, page, parent);
                        nextParent = component;
                    }else{
                        nextParent = propertyTagHandler(xml, parent);
                    }
                }
                if(xml.children().length() > 0){
                    visitNode(xml.children(), page, nextParent);
                }
            }
        }
        
        //处理非组件的标签，比如DataGrid里的columns标签
        private function propertyTagHandler(xml:XML, parent:Object):Object{
            var classInfo:XML = describeType(parent);
            var propertyName:String = xml.localName();//下级节点是组件的一个属性
            var varType:String = classInfo.accessor.(@name==propertyName).@type;//属性类型
            var result:Object;
            varType = varType.toLowerCase();
            if(varType == 'array'){
                result = new Array();
            }
            //parent[propertyName]=result;
            return result;
        }
        
        //处理组件
        private function componentHandler(xml:XML, page:FlexPage, parent:Object):Object{
            var component:Object = createComponent(xml.localName(), xml.namespace());
            if(component == null){
                trace(xml.name()+"创建失败");
                return null;
            }
            setProperty(xml, component);
            page.putComponentToContext(component);
            if(parent is UIComponent){
                addChild(component as UIComponent, parent);
            }else{
                if(parent is Array){
                    var array:Array = parent as Array;
                    array.push(component);
                }
            }
            return component;
        }
        
        //判断是否是容器
        private function isContainer(component:Object):Boolean{
            return component is SkinnableContainer || component is Group || component is Container;
        }
        
        //添加组件
        private function addChild(component:UIComponent, parent:Object):void{
            if(parent is SkinnableContainer){
                //spark组件
                var container:SkinnableContainer = parent as SkinnableContainer;
                container.addElement(component);
            }else if(parent is Group){
                //halo组件
                var group:Group = parent as Group;
                group.addElement(component);
            }else if(parent is Container){
                //halo组件
                var haloContainer:Container = parent as Container;
                haloContainer.addChild(component);
            }
        }
        
        //创建组件
        private function createComponent(name:String, namespace:String):Object{
            var packageList:Array = NAME_SPACE_MAPPING[namespace];
            var script:String;
            var component:Object=null;
            if(packageList){
                for(var i:int=0;i<packageList.length;i++){
                    try{
                        script = 'import '+packageList[i]+name+';\n';
                        script += 'new '+name+';';
                        component = D.eval(script);//大部分情况或返回UIComponent，但如果是属性标签时则可能是其他类型
                        return component;
                    }catch(e:Error){
                        trace(e.getStackTrace());
                        continue;
                    }
                }
            }
            return component;
        }
        
        //设置组件属性
        private function setProperty(xml:XML, component:Object):void{
            var attrs:XMLList = xml.attributes();
            var context:Object = {com:component};
            var script:String;
            var propertyName:String;
            var propertyValue:String;
            for(var i:int=0;i<attrs.length();i++){
                trace(attrs[i].name()+" : "+ attrs[i]);
                propertyName = attrs[i].name();
                propertyValue = attrs[i];
                //长度或高度是百分比
                if((propertyName == 'width' || propertyName == 'height') && isPercent(propertyValue)){
                    propertyName = 'percent'+firstCharToUpper(propertyName);
                    propertyValue = propertyValue.replace('%','');
                }
                script = 'com.'+propertyName+'=';
                if(isNaN(attrs[i])){
                    script += '"'+propertyValue+'"';
                }else{
                    script += propertyValue;
                }
                try{
                    D.eval(script, context);
                }catch(e:Error){
                    trace(e.getStackTrace());
                }
            }
        }
        
        //判断是否百分比格式
        private function isPercent(val:String):Boolean{
            return val.indexOf('%') == val.length - 1;
        }
        
        //首字母大写
        private function firstCharToUpper(s:String):String{
            return s.replace(/(\w)/,function($0:String, $1:String, $2:String, $3:String){
                return $1.toUpperCase();
            });
        }
    }
}